package com.cwx.mychat.websocket;

import com.cwx.mychat.entity.dto.TokenUserInfoDto;
import com.cwx.mychat.entity.enums.ExceptionBizCodeEnum;
import com.cwx.mychat.exception.BusinessException;
import com.cwx.mychat.utils.common.CommonUtil;
import com.cwx.mychat.utils.redis.RedisComponent;
import com.cwx.mychat.utils.stringUtils.StringUtil;
import com.cwx.mychat.websocket.context.ChannelContextUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


/**
 * 作者： cwx
 * 时间： 2024/9/20 13:46
 * 版本： 1.0
 * 注释：
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class HandlerWebSocket extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Resource
    private RedisComponent redisComponent;

    @Resource
    private ChannelContextUtil channelContextUtil;

    /**
     * 接收文本消息
     * @param channelHandlerContext
     * @param textWebSocketFrame
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        Channel channel = channelHandlerContext.channel();
        Attribute<String> attr = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        String userId = attr.get();
        if(userId == null){
            log.info("用户断开");
        }
        //设置心跳
        redisComponent.saveUserHeartbeat(userId);
    }


    /**
     * 通道就绪后调用，一般做初始化
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        Attribute<String> attr = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        String userId = attr.get();
        log.info("用户{}加入...", userId);
        super.channelActive(ctx);
    }

    /**
     * 通道断开时
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        Attribute<String> attr = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        String userId = attr.get();
        log.info("用户{},连接断开...", userId);
        channelContextUtil.removeContext(channel, userId);
    }

    /**
     * 处理用户事件的回调方法
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete){
            WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            String uri = complete.requestUri();
            String token = getToken(uri);
            if(token == null){
                ctx.channel().close();
                return;
            }
            String userId = CommonUtil.checkToken(token);
            TokenUserInfoDto tokenUserInfoDto = redisComponent.getTokenUserInfoDto(userId);
            if(tokenUserInfoDto == null){
                ctx.channel().close();
                return;
            }
            channelContextUtil.addContext(userId, ctx.channel());
        }
    }

    private String getToken(String uri){
        if(StringUtil.isEmpty(uri) || uri.indexOf("2") == -1){
            return null;
        }
        String[] split = uri.split("\\?");
        if(split.length != 2){
            return null;
        }
        String[] params = split[1].split("=");
        if(params.length != 2){
            return null;
        }
        return params[1];
    }
}
